package com.example.springboot.service.impl;

import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import com.example.springboot.common.Constants;
import com.example.springboot.controller.dto.LoginDto;
import com.example.springboot.controller.request.BaseRequest;
import com.example.springboot.controller.request.LoginRequest;
import com.example.springboot.controller.request.PasswordRequest;
import com.example.springboot.entity.Admin;
import com.example.springboot.exception.ServiceException;
import com.example.springboot.mapper.AdminMapper;
import com.example.springboot.service.IAdminService;
import com.example.springboot.utils.TokenUtils;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * Description:业务层实现类
 *
 * @Author 马钰涵
 * @Create 2023/8/5 9:15
 * @Version 1.0
 */
@Slf4j
@Service
public class AdminServiceImpl implements IAdminService {

    @Autowired
    private AdminMapper adminMapper;


    @Override
    public List<Admin> list() {
        return adminMapper.list();
    }

    @Override
    public PageInfo<Admin> page(BaseRequest baseRequest) {
        PageHelper.startPage(baseRequest.getPageNum(), baseRequest.getPageSize());
        List<Admin> admins = adminMapper.listByCondition(baseRequest);
        return new PageInfo<>(admins);
    }

    @Override
    public void save(Admin admin) {
        if (StrUtil.isBlank(admin.getPassword())) {//新增管理员的默认密码"123456"
            admin.setPassword(Constants.DEFAULT_PASSWORD);
        }
        admin.setPassword(securePassword(admin.getPassword()));//调用加密方法加密密码
        try {
            adminMapper.save(admin);
        } catch (DuplicateKeyException e) {
            log.error(Constants.ADD_USER_ERROR, admin.getUsername(), e);
            throw new ServiceException(Constants.USER_IS_EXITS_CODE, Constants.USER_IS_EXITS_MSG);
        }
    }

    @Override
    public Admin getById(Integer id) {
        return adminMapper.getById(id);
    }

    @Override
    public void update(Admin admin) {
        adminMapper.updateById(admin);
    }


    @Override
    public void deleteById(Integer id) {
        adminMapper.deleteById(id);
    }

    @Override
    public LoginDto login(LoginRequest request) {
        Admin admin = null;//查询用户信息并且校验用户名是否已存在
        try {
            admin = adminMapper.getByUsername(request.getUsername());
        } catch (Exception e) { //该用户已存在，返回403和提示信息
            log.error(Constants.ADD_USER_ERROR, request.getUsername(), e);
            throw new ServiceException(Constants.USER_IS_EXITS_CODE, Constants.USER_IS_EXITS_MSG);
        }
        if (admin == null) {        //用户名或密码错误
            throw new ServiceException(Constants.USERNAME_OR_PASSWORD_ERROR);
        }
        String securePassword = securePassword(request.getPassword());//密码加密
        if (!securePassword.equals(admin.getPassword())) {
            throw new ServiceException(Constants.USERNAME_OR_PASSWORD_ERROR);
        }
        if (!admin.getStatus()) {           //用户被禁用，返回402和提示信息
            throw new ServiceException(Constants.STATUS_DISABLE_CODE, Constants.USER_IS_DISABLE);
        }
        LoginDto loginDto = new LoginDto();         //LoginDto
        BeanUtils.copyProperties(admin, loginDto);           //admin对象复制到loginDto对象

        String token = TokenUtils.genToken(String.valueOf(admin.getId()), admin.getPassword());//生成token
        loginDto.setToken(token);
        return loginDto;
    }

    @Override
    public void updatePassword(PasswordRequest request) {//要对新密码进行加密
        request.setNewPassword(securePassword(request.getNewPassword()));
        int count = adminMapper.updatePassword(request);
        if (count <= 0) {
            throw new ServiceException(Constants.UPDATE_PASSWORD_ERROR);
        }
    }

    //封装密码加密的方法
    private String securePassword(String password) {
        return SecureUtil.md5(password + Constants.SAIT_PASSWORD);//设置md5加密，再加盐
    }
}
